package com.zk.yygh.user.controller.api;

import com.alibaba.fastjson.JSONObject;
import com.zk.yygh.hosp.exception.HospitalException;
import com.zk.yygh.hosp.helper.JwtHelper;
import com.zk.yygh.hosp.result.Result;
import com.zk.yygh.hosp.result.ResultCodeEnum;
import com.zk.yygh.model.user.UserInfo;
import com.zk.yygh.user.config.ConstantPropertiesUtil;
import com.zk.yygh.user.service.UserInfoService;
import com.zk.yygh.user.utils.HttpClientUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: 张凯
 * @date: 2022/6/14 - 15:59
 */
@Api(value = "微信登录相关api")
@Controller
@RequestMapping("/api/ucenter/wx")
public class WeChatApiController {
    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @ApiOperation(value = "1.获取微信登录参数")
    @GetMapping("getParams")
    @ResponseBody
    public Result getParams(){
        Map<String,Object> params=new HashMap<>();
        try {
            params.put("appid", ConstantPropertiesUtil.WX_OPEN_APP_ID);
            String redirectUrl = URLEncoder.encode(ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL, "UTF-8");
            params.put("redirectUri",redirectUrl);
//            params.put("redirectUri",ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL);
            params.put("scope","snsapi_login");
            params.put("state",System.currentTimeMillis()+"");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return Result.ok(params);
    }

    @ApiOperation(value = "2.微信登录回调函数")
    @GetMapping("callback")
    public String callBack(String code,String state) throws UnsupportedEncodingException {
        //一、通过临时票据(code，appid，appscrect)获取(access_token,openid)
        if (StringUtils.isEmpty(state) || StringUtils.isEmpty(code)) {
            System.out.println("非法回调请求");
            throw new HospitalException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
        }
        //1.1 封装微信后台接口及相关参数
        StringBuffer baseAccessTokenUrl = new StringBuffer()
                .append("https://api.weixin.qq.com/sns/oauth2/access_token")
                .append("?appid=%s")
                .append("&secret=%s")
                .append("&code=%s")
                .append("&grant_type=authorization_code");
        String accessTokenUrl = String.format(baseAccessTokenUrl.toString(),
                ConstantPropertiesUtil.WX_OPEN_APP_ID,
                ConstantPropertiesUtil.WX_OPEN_APP_SECRET,
                code);
        //1.2 通过HttpClient进行请求调用获取结果
        String result = null;
        try {
            result = HttpClientUtils.get(accessTokenUrl);
        } catch (Exception e) {
            System.out.println("获取accessToken失败");
            throw new HospitalException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
        }
        System.out.println("使用code换取的access_token结果 = " + result);
        //1.3 将返回结果进行json对象转换，并获取accessToken，openId
        JSONObject resultJson = JSONObject.parseObject(result);
        if(resultJson.getString("errcode") != null){
            System.out.println("获取access_token失败：" + resultJson.getString("errcode") + resultJson.getString("errmsg"));
            throw new HospitalException(ResultCodeEnum.FETCH_ACCESSTOKEN_FAILD);
        }
        String accessToken = resultJson.getString("access_token");
        String openId = resultJson.getString("openid"); //用户的唯一标识，appId为第三方应用的唯一标识


        //二、通过access_token，openid获取用户基本信息，以及增查数据库登录
        //2.1 根据openId查询数据库
        UserInfo userInfo = userInfoService.selectUserInfoByOpenId(openId);
        //2.2 结果为空说明用户第一次扫描
        if (userInfo==null){
            //2.3 根据（accessToken，openId）获取并解析用户基本信息
            String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo"+
                    "?access_token=%s"+
                    "&openid=%s";
            String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openId);
            String resultUserInfo = null;
            try {
                resultUserInfo = HttpClientUtils.get(userInfoUrl);
            } catch (Exception e) {
                throw new HospitalException(ResultCodeEnum.FETCH_USERINFO_ERROR);
            }
            System.out.println("使用access_token获取用户信息的结果 = "+ resultUserInfo);

            JSONObject resultUserInfoJson = JSONObject.parseObject(resultUserInfo);
            if(resultUserInfoJson.getString("errcode") != null){
                System.out.println("获取用户信息失败："+ resultUserInfoJson.getString("errcode") + resultUserInfoJson.getString("errmsg"));
                throw new HospitalException(ResultCodeEnum.FETCH_USERINFO_ERROR);
            }
            //2.4 将用户基本信息写入数据库
            String nickname = resultUserInfoJson.getString("nickname");
            String headimgurl = resultUserInfoJson.getString("headimgurl");
            userInfo = new UserInfo();
            userInfo.setOpenid(openId);
            userInfo.setNickName(nickname);
            userInfo.setStatus(1);
            userInfoService.save(userInfo);
        }
        //三、封装并重定向前端页面
        Map<String, Object> map = new HashMap<>();
        //3.1 封装name信息
        String name = userInfo.getName();
        if(StringUtils.isEmpty(name)) {
            name = userInfo.getNickName();
        }
        if(StringUtils.isEmpty(name)) {
            name = userInfo.getPhone();
        }
        map.put("name", name);
        //3.2 根据用户是否绑定手机号封装openid信息：为了让前端进行手机号绑定
        if(StringUtils.isEmpty(userInfo.getPhone())) {
            map.put("openid", userInfo.getOpenid());
        } else {
            map.put("openid", "");
        }
        //3.3 生成token
        String token = JwtHelper.createToken(userInfo.getId(), name);
        map.put("token", token);
        return "redirect:"+ ConstantPropertiesUtil.YYGH_BASE_URL + "/weixin/callback?token="+map.get("token")+"&openid="+map.get("openid")+"&name="+URLEncoder.encode((String)map.get("name"),"utf-8");
    }

}
